import java.util.Random;

/**
 * BinaryOperation类的测试类
 */
public class BinaryOperationTest {
    
    // 为了能够直接运行测试，添加main方法
    public static void main(String[] args) {
        System.out.println("开始测试BinaryOperation类...");
        
        BinaryOperationTest test = new BinaryOperationTest();
        int passedTests = 0;
        int totalTests = 0;
        
        try {
            // 启用断言
            boolean assertionsEnabled = false;
            assert assertionsEnabled = true; // 这行会被优化掉，但会启用断言
            
            // 测试默认构造函数
            System.out.println("1. 测试构造函数...");
            totalTests++;
            test.testConstructor();
            passedTests++;
            System.out.println("✓ 构造函数测试通过");
            
            // 测试访问器方法
            System.out.println("2. 测试访问器方法...");
            totalTests++;
            test.testAccessors();
            passedTests++;
            System.out.println("✓ 访问器方法测试通过");
            
            // 测试toString方法
            System.out.println("3. 测试toString方法...");
            totalTests++;
            test.testToString();
            passedTests++;
            System.out.println("✓ toString方法测试通过");
            
            // 测试construct方法
            System.out.println("4. 测试construct方法...");
            totalTests++;
            test.testConstruct();
            passedTests++;
            System.out.println("✓ construct方法测试通过");
            
            // 测试generateAdditionOperation方法
            System.out.println("5. 测试generateAdditionOperation方法...");
            totalTests++;
            test.testGenerateAdditionOperation();
            passedTests++;
            System.out.println("✓ generateAdditionOperation方法测试通过");
            
            // 测试generateSubstractOperation方法
            System.out.println("6. 测试generateSubstractOperation方法...");
            totalTests++;
            test.testGenerateSubstractOperation();
            passedTests++;
            System.out.println("✓ generateSubstractOperation方法测试通过");
            
            // 测试generateBinaryOperation方法
            System.out.println("7. 测试generateBinaryOperation方法...");
            totalTests++;
            test.testGenerateBinaryOperation();
            passedTests++;
            System.out.println("✓ generateBinaryOperation方法测试通过");
            
            // 测试equals方法
            System.out.println("8. 测试equals方法...");
            totalTests++;
            test.testEquals();
            passedTests++;
            System.out.println("✓ equals方法测试通过");
            
            // 测试hashCode方法
            System.out.println("9. 测试hashCode方法...");
            totalTests++;
            test.testHashCode();
            passedTests++;
            System.out.println("✓ hashCode方法测试通过");
            
            // 测试边界条件
            System.out.println("10. 测试边界条件...");
            totalTests++;
            test.testBoundaryConditions();
            passedTests++;
            System.out.println("✓ 边界条件测试通过");
            
            System.out.println("\n测试完成！通过: " + passedTests + "/" + totalTests);
        } catch (AssertionError e) {
            System.out.println("✗ 测试失败: " + e.getMessage());
            e.printStackTrace();
            System.out.println("\n测试完成！通过: " + passedTests + "/" + totalTests);
        } catch (Exception e) {
            System.out.println("✗ 测试过程中发生异常: " + e.getMessage());
            e.printStackTrace();
            System.out.println("\n测试完成！通过: " + passedTests + "/" + totalTests);
        }
    }
    
    /**
     * 测试默认构造函数
     */
    private void testConstructor() {
        BinaryOperation operation = new BinaryOperation();
        assert operation != null : "构造函数返回null";
    }
    
    /**
     * 测试访问器方法
     */
    private void testAccessors() {
        // 使用固定种子确保测试的可重复性
        Random random = new Random(42);
        BinaryOperation operation = new BinaryOperation();
        operation.generateAdditionOperation(random);
        
        // 验证属性不为默认值
        assert operation.getLeftOperand() > 0 : "左操作数应该大于0";
        assert operation.getRightOperand() > 0 : "右操作数应该大于0";
        assert operation.getOperator() == '+' : "运算符应该是+";
        assert operation.getResult() == operation.getLeftOperand() + operation.getRightOperand() : "结果计算错误";
    }
    
    /**
     * 测试toString方法
     */
    private void testToString() {
        Random random = new Random(100);
        BinaryOperation operation = new BinaryOperation();
        operation.generateAdditionOperation(random);
        
        String result = operation.toString();
        String expected = operation.getLeftOperand() + " " + operation.getOperator() + " " + 
                          operation.getRightOperand() + " = " + operation.getResult();
        
        assert result.equals(expected) : "toString方法输出不正确";
    }
    
    /**
     * 测试construct方法
     */
    private void testConstruct() {
        Random random = new Random(200);
        BinaryOperation operation = new BinaryOperation();
        operation.construct(random);
        
        // 验证构造后的值是否有效
        assert operation.getLeftOperand() > 0 : "左操作数应该大于0";
        assert operation.getRightOperand() > 0 : "右操作数应该大于0";
        assert operation.getOperator() == '+' || operation.getOperator() == '-' : "运算符应该是+或-";
        
        // 验证结果计算是否正确
        if (operation.getOperator() == '+') {
            assert operation.getResult() == operation.getLeftOperand() + operation.getRightOperand() : "加法结果计算错误";
        } else {
            assert operation.getResult() == operation.getLeftOperand() - operation.getRightOperand() : "减法结果计算错误";
        }
    }
    
    /**
     * 测试generateAdditionOperation方法
     */
    private void testGenerateAdditionOperation() {
        Random random = new Random(300);
        BinaryOperation operation = new BinaryOperation();
        
        // 测试多次生成加法运算
        for (int i = 0; i < 10; i++) {
            operation.generateAdditionOperation(random);
            
            assert operation.getOperator() == '+' : "运算符应该是+";
            assert operation.getLeftOperand() >= 1 && operation.getLeftOperand() <= 99 : "左操作数范围错误";
            assert operation.getRightOperand() >= 1 && operation.getRightOperand() <= 99 : "右操作数范围错误";
            assert operation.getResult() <= 100 : "加法结果应该小于等于100";
            assert operation.getResult() == operation.getLeftOperand() + operation.getRightOperand() : "加法结果计算错误";
        }
    }
    
    /**
     * 测试generateSubstractOperation方法
     */
    private void testGenerateSubstractOperation() {
        Random random = new Random(400);
        BinaryOperation operation = new BinaryOperation();
        
        // 测试多次生成减法运算
        for (int i = 0; i < 10; i++) {
            operation.generateSubstractOperation(random);
            
            assert operation.getOperator() == '-' : "运算符应该是-";
            assert operation.getLeftOperand() >= 1 && operation.getLeftOperand() <= 99 : "左操作数范围错误";
            assert operation.getRightOperand() >= 1 && operation.getRightOperand() <= operation.getLeftOperand() : "右操作数应该小于等于左操作数";
            assert operation.getResult() >= 0 : "减法结果应该大于等于0";
            assert operation.getResult() == operation.getLeftOperand() - operation.getRightOperand() : "减法结果计算错误";
        }
    }
    
    /**
     * 测试generateBinaryOperation方法
     */
    private void testGenerateBinaryOperation() {
        Random random = new Random(500);
        BinaryOperation operation = new BinaryOperation();
        
        // 测试多次生成混合运算
        boolean hasAddition = false;
        boolean hasSubtraction = false;
        
        for (int i = 0; i < 20; i++) {
            operation.generateBinaryOperation(random);
            
            if (operation.getOperator() == '+') {
                hasAddition = true;
                assert operation.getResult() == operation.getLeftOperand() + operation.getRightOperand() : "加法结果计算错误";
            } else {
                hasSubtraction = true;
                assert operation.getResult() == operation.getLeftOperand() - operation.getRightOperand() : "减法结果计算错误";
            }
        }
        
        // 确保至少生成了加法和减法各一次
        assert hasAddition && hasSubtraction : "应该生成加法和减法两种运算";
    }
    
    /**
     * 测试equals方法的所有情况
     */
    private void testEquals() {
        // 测试相同对象
        BinaryOperation operation = new BinaryOperation();
        operation.generateAdditionOperation(new Random(600));
        assert operation.equals(operation) : "对象应该等于自身";
        
        // 测试null对象
        assert !operation.equals(null) : "对象不应该等于null";
        
        // 测试不同类型对象
        assert !operation.equals(new Object()) : "对象不应该等于不同类型的对象";
        
        // 测试相同的加法运算
        Random random = new Random(700);
        BinaryOperation op1 = new BinaryOperation();
        BinaryOperation op2 = new BinaryOperation();
        
        op1.generateAdditionOperation(random);
        op2.generateAdditionOperation(new Random(700));
        
        assert op1.equals(op2) : "相同的加法运算应该相等";
        
        // 测试不同的加法运算
        op1.generateAdditionOperation(new Random(800));
        op2.generateAdditionOperation(new Random(900));
        
        // 只有当操作数确实不同时才进行断言
        if (op1.getLeftOperand() != op2.getLeftOperand() || 
            op1.getRightOperand() != op2.getRightOperand() ||
            op1.getLeftOperand() != op2.getRightOperand() ||
            op1.getRightOperand() != op2.getLeftOperand()) {
            assert !op1.equals(op2) : "不同的加法运算应该不相等";
        }
        
        // 测试相同的减法运算
        op1.generateSubstractOperation(new Random(1000));
        op2.generateSubstractOperation(new Random(1000));
        
        assert op1.equals(op2) : "相同的减法运算应该相等";
        
        // 测试不同的减法运算
        op1.generateSubstractOperation(new Random(1100));
        op2.generateSubstractOperation(new Random(1200));
        
        if (op1.getLeftOperand() != op2.getLeftOperand() || 
            op1.getRightOperand() != op2.getRightOperand()) {
            assert !op1.equals(op2) : "不同的减法运算应该不相等";
        }
        
        // 测试加法和减法的比较
        op1.generateAdditionOperation(new Random(1300));
        op2.generateSubstractOperation(new Random(1400));
        
        assert !op1.equals(op2) : "加法和减法运算应该不相等";
    }
    
    /**
     * 测试hashCode方法
     */
    private void testHashCode() {
        // 使用固定的随机数种子来生成可重复的测试数据
        Random random = new Random(1500);
        
        // 测试多次生成的相同运算应该有相同的hashCode
        for (int i = 0; i < 5; i++) {
            BinaryOperation op1 = new BinaryOperation();
            BinaryOperation op2 = new BinaryOperation();
            
            // 先生成一个加法运算
            op1.generateAdditionOperation(new Random(i * 100));
            op2.generateAdditionOperation(new Random(i * 100));
            
            // 因为equals返回true，所以hashCode应该相等
            assert op1.hashCode() == op2.hashCode() : "相等的对象应该有相同的hashCode";
            
            // 再生成一个减法运算
            op1.generateSubstractOperation(new Random(i * 200));
            op2.generateSubstractOperation(new Random(i * 200));
            
            // 因为equals返回true，所以hashCode应该相等
            assert op1.hashCode() == op2.hashCode() : "相等的对象应该有相同的hashCode";
        }
    }
    
    /**
     * 测试边界条件
     */
    private void testBoundaryConditions() {
        // 创建一个简单的测试方法来验证边界条件
        testAdditionBoundary();
        testSubtractionBoundary();
    }
    
    private void testAdditionBoundary() {
        // 测试加法边界条件
        for (int i = 0; i < 50; i++) {
            Random random = new Random(i * 300);
            BinaryOperation operation = new BinaryOperation();
            operation.generateAdditionOperation(random);
            
            // 验证结果是否符合约束
            assert operation.getResult() <= 100 : "加法结果应该小于等于100";
            assert operation.getLeftOperand() >= 1 && operation.getLeftOperand() <= 99 : "左操作数范围错误";
            assert operation.getRightOperand() >= 1 && operation.getRightOperand() <= 99 : "右操作数范围错误";
        }
    }
    
    private void testSubtractionBoundary() {
        // 测试减法边界条件
        for (int i = 0; i < 50; i++) {
            Random random = new Random(i * 400);
            BinaryOperation operation = new BinaryOperation();
            operation.generateSubstractOperation(random);
            
            // 验证结果是否符合约束
            assert operation.getResult() >= 0 : "减法结果应该大于等于0";
            assert operation.getRightOperand() <= operation.getLeftOperand() : "右操作数应该小于等于左操作数";
            assert operation.getLeftOperand() >= 1 && operation.getLeftOperand() <= 99 : "左操作数范围错误";
            assert operation.getRightOperand() >= 1 : "右操作数应该大于等于1";
        }
    }
}